{
  "nbformat": 4,
  "nbformat_minor": 0,
  "metadata": {
    "colab": {
      "name": "training_loops.ipynb",
      "version": "0.3.2",
      "provenance": [],
      "private_outputs": true,
      "collapsed_sections": [
        "MhoQ0WE77laV"
      ],
      "toc_visible": true
    },
    "kernelspec": {
      "display_name": "Python 3",
      "language": "python",
      "name": "python3"
    },
    "language_info": {
      "codemirror_mode": {
        "name": "ipython",
        "version": 3
      },
      "file_extension": ".py",
      "mimetype": "text/x-python",
      "name": "python",
      "nbconvert_exporter": "python",
      "pygments_lexer": "ipython3",
      "version": "3.7.0"
    }
  },
  "cells": [
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "MhoQ0WE77laV"
      },
      "source": [
        "##### Copyright 2019 The TensorFlow Authors."
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "cellView": "form",
        "colab_type": "code",
        "id": "_ckMIh7O7s6D",
        "colab": {}
      },
      "source": [
        "#@title Licensed under the Apache License, Version 2.0 (the \"License\");\n",
        "# you may not use this file except in compliance with the License.\n",
        "# You may obtain a copy of the License at\n",
        "#\n",
        "# https://www.apache.org/licenses/LICENSE-2.0\n",
        "#\n",
        "# Unless required by applicable law or agreed to in writing, software\n",
        "# distributed under the License is distributed on an \"AS IS\" BASIS,\n",
        "# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n",
        "# See the License for the specific language governing permissions and\n",
        "# limitations under the License."
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "jYysdyb-CaWM"
      },
      "source": [
        "# Egitim donguleri ile tf.distribute.Strategy"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "S5Uhzt6vVIB2"
      },
      "source": [
        "<table class=\"tfo-notebook-buttons\" align=\"left\">\n",
        "  <td>\n",
        "    <a target=\"_blank\" href=\"https://colab.research.google.com/github/tensorflow/docs/blob/master/site/tr/r1/tutorials/distribute/training_loops.ipynb\"><img src=\"https://www.tensorflow.org/images/colab_logo_32px.png\" />Run in Google Colab</a>\n",
        "  </td>\n",
        "  <td>\n",
        "    <a target=\"_blank\" href=\"https://github.com/tensorflow/docs/blob/master/site/tr/r1/tutorials/distribute/training_loops.ipynb\"><img src=\"https://www.tensorflow.org/images/GitHub-Mark-32px.png\" />View source on GitHub</a>\n",
        "  </td>\n",
        "</table>"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "-adnPCDYkI8e"
      },
      "source": [
        "Note: Bu dökümanlar TensorFlow gönüllü kullanıcıları tarafından çevirilmiştir.\n",
        "Topluluk tarafından sağlananan çeviriler gönüllülerin ellerinden geldiğince\n",
        "güncellendiği için [Resmi İngilizce dökümanlar](https://www.tensorflow.org/?hl=en)\n",
        "ile bire bir aynı olmasını garantileyemeyiz. Eğer bu tercümeleri iyileştirmek\n",
        "için önerileriniz var ise lütfen [tensorflow/docs](https://github.com/tensorflow/docs)\n",
        "havuzuna pull request gönderin. Gönüllü olarak çevirilere katkıda bulunmak için\n",
        "[docs-tr@tensorflow.org](https://groups.google.com/a/tensorflow.org/forum/#!forum/docs-tr)\n",
        "listesi ile iletişime geçebilirsiniz."
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "FbVhjPpzn6BM"
      },
      "source": [
        "Bu rehber egitim donguleri ile [`tf.distribute.Strategy`](https://www.tensorflow.org/r1/guide/distribute_strategy)'nin nasil kullanildigini gosteriyor. Basit bir CNN modelini Fashion MNIST veri seti ile egitecegiz. Bu veri seti icinde 28X28 boyutunda 60000 egitim resmini ve 28X28 boyutunda 10000 test resmini barindirir.\n",
        "\n",
        "Burada bize esneklik ve daha cok kontrol kazandirmasi icin ozellestirilmis egitim donguleri kullanacagiz. Ustelik, bu ozel donguler modeli ve egitim dongulerindeki hatalari ayiklamamizi da kolaylastiracaktir."
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab_type": "code",
        "id": "dzLKpmZICaWN",
        "colab": {}
      },
      "source": [
        "from __future__ import absolute_import, division, print_function, unicode_literals\n",
        "\n",
        "# TensorFlow'u yukleyelim\n",
        "import tensorflow as tf\n",
        "\n",
        "# Yardimci kutuphaneler\n",
        "import numpy as np\n",
        "import os\n",
        "\n",
        "print(tf.__version__)"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "MM6W__qraV55"
      },
      "source": [
        "## Fashion MNIST veri setini indirelim"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab_type": "code",
        "id": "7MqDQO0KCaWS",
        "colab": {}
      },
      "source": [
        "fashion_mnist = tf.keras.datasets.fashion_mnist\n",
        "\n",
        "(train_images, train_labels), (test_images, test_labels) = fashion_mnist.load_data()\n",
        "\n",
        "# Diziye yeni bir boyut ekleyelim-> new shape == (28, 28, 1)\n",
        "# Bunu yapmamizin sebebi ise modelimizin ilk katmaninin katlamali olmasi\n",
        "# ve 4D bir girdiye ihtiyac duyar (batch_size, height, width, channels).\n",
        "# batch_size boyutunu daha sonra ekleyecegiz.\n",
        "train_images = train_images[..., None]\n",
        "test_images = test_images[..., None]\n",
        "\n",
        "# Resimleri [0, 1] araligina indirgeyelim.\n",
        "train_images = train_images / np.float32(255)\n",
        "test_images = test_images / np.float32(255)\n",
        "\n",
        "train_labels = train_labels.astype('int64')\n",
        "test_labels = test_labels.astype('int64')"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "4AXoHhrsbdF3"
      },
      "source": [
        "## Degiskenleri ve grafigi dagitmak icin bir taktik olusturalim"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "5mVuLZhbem8d"
      },
      "source": [
        "`tf.distribute.MirroredStrategy` nasil calisir?\n",
        "\n",
        "*   Butun degiskenler ve model grafigi birkac kere kopyalanir.\n",
        "*   Girdi bu kopyalara esit olarak dagitilir.\n",
        "*   Her kopya verilen girdiye gore bir kayip ve degisim tablosu hesaplar.\n",
        "*   Butun degisim verileri toplanir ve kopyalardaki degerler bu toplama gore guncellenir.\n",
        "*   Bu islemden sonra, ayni guncelleme degiskenlerin kopyalarina da uygulanir. \n",
        "\n",
        "Note: Butun kodu tek bir kapsam icine koyabilirsiniz, fakat biz burada daha aciklayici olmasi icin kodu boluyoruz.\n"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab_type": "code",
        "id": "F2VeZUWUj5S4",
        "colab": {}
      },
      "source": [
        "# Eger kullanilacak cihazlar `tf.distribute.MirroredStrategy` yapicisinda belirtilmediyse\n",
        "# otomatik olarak bulunacaktir.\n",
        "strategy = tf.distribute.MirroredStrategy()"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab_type": "code",
        "id": "ZngeM_2o0_JO",
        "colab": {}
      },
      "source": [
        "print ('Number of devices: {}'.format(strategy.num_replicas_in_sync))"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "k53F5I_IiGyI"
      },
      "source": [
        "## Girdi hattinin kurulmasi"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "0Qb6nDgxiN_n"
      },
      "source": [
        "Eger bir model birden fazla GPU'da egitiliyorsa, grup boyutu buna orantili olarak arttirilmalidir ki fazla bilgisayar gucunu verimli bir sekilde kullanabilelim. Ayrica, egitim hizi da orantili olarak ayarlanmaidir. "
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab_type": "code",
        "id": "jwJtsCQhHK-E",
        "colab": {}
      },
      "source": [
        "BUFFER_SIZE = len(train_images)\n",
        "\n",
        "BATCH_SIZE_PER_REPLICA = 64\n",
        "BATCH_SIZE = BATCH_SIZE_PER_REPLICA * strategy.num_replicas_in_sync\n",
        "\n",
        "EPOCHS = 10"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "J7fj3GskHC8g"
      },
      "source": [
        "`strategy.make_dataset_iterator`, veriyi kopyalara esit olarak dagitan bir iterator olusturur. \n",
        "\n",
        "\n",
        "Note: Bu API yakin zamanda degisecektir."
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab_type": "code",
        "id": "WYrMNNDhAvVl",
        "colab": {}
      },
      "source": [
        "with strategy.scope():\n",
        "  train_dataset = tf.data.Dataset.from_tensor_slices(\n",
        "  (train_images, train_labels)).shuffle(BUFFER_SIZE).batch(BATCH_SIZE)\n",
        "  train_iterator = strategy.make_dataset_iterator(train_dataset)\n",
        "\n",
        "  test_dataset = tf.data.Dataset.from_tensor_slices(\n",
        "      (test_images, test_labels)).batch(BATCH_SIZE)\n",
        "  test_iterator = strategy.make_dataset_iterator(test_dataset)"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "bAXAo_wWbWSb"
      },
      "source": [
        "## Modelin olusturulmasi\n",
        "\n",
        "`tf.keras.Sequential` ile modelimizi olusturalim. Model Subclassing API'yini da kullanarak bu islemi yapabiliriz."
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab_type": "code",
        "id": "9ODch-OFCaW4",
        "colab": {}
      },
      "source": [
        "with strategy.scope():\n",
        "  model = tf.keras.Sequential([\n",
        "      tf.keras.layers.Conv2D(32, 3, activation='relu',\n",
        "                             input_shape=(28, 28, 1)),\n",
        "      tf.keras.layers.MaxPooling2D(),\n",
        "      tf.keras.layers.Conv2D(64, 3, activation='relu'),\n",
        "      tf.keras.layers.MaxPooling2D(),\n",
        "      tf.keras.layers.Flatten(),\n",
        "      tf.keras.layers.Dense(64, activation='relu'),\n",
        "      tf.keras.layers.Dense(10, activation='softmax')\n",
        "    ])\n",
        "  optimizer = tf.train.GradientDescentOptimizer(0.001)"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "e-wlFFZbP33n"
      },
      "source": [
        "## Kayip fonksiyonunu tanimlayalim\n",
        "\n",
        "Normalde, eger 1 GPU/CPU'lu bir makine kullaniyorsak, kayip girdi grubundaki ornek sayisina bolunur.\n",
        "\n",
        "*Peki `tf.distribute.Strategy` ile kayip nasil hesaplanir?*\n",
        "\n",
        "> Ornegin, 4 GPU'muz ve boyutu 64 olan girdimiz oldugunu varsayalim. Bu girdiler esit olarak 4 GPU (4 kopya) ustune bolunur, yani her kopyaya giden girdi grub boyutu 16 idir.\n",
        "\n",
        "> Her kopyadaki model icindeki girdinin ustunden gecerek kayip degerini hesaplar. Simdi, bu kayip degerini icindeki girdi sayisina (16) bolmek yerine, en bastaki evrensel girdi miktarina (64) boler. \n",
        "\n",
        "*Neden bu islem boyle yaplir?*\n",
        "\n",
        "> Cunku degisim degerleri her kopyada hesaplandiktan sonra, butun kopyalardaki degerler butun degisim degerlerinin toplamina esitlenir.\n",
        "\n",
        "*Bunu TensorFlow'da nasil yapabiliriz?*\n",
        "\n",
        "Eger ozellestirilmis bir egitim dongusu yaziyorsaniz, her ornekteki kayiplari toplayip butun orneklerin toplamina bolmelisiniz:\n",
        "\n",
        "```\n",
        "GLOBAL_BATCH_SIZE:`scale_loss = tf.reduce_sum(loss) * (1. / GLOBAL_BATCH_SIZE)`\n",
        "```\n",
        "\n",
        "* `tf.reduce_mean` metodunu kullanmanizi tavsiye etmiyoruz. Bu metod kayip degerini kopyalardaki ornek sayisina boler ki bu her adimda degisebilir.\n",
        "\n",
        "* Bu indirgeme ve olcekleme keras'ta otomatok olarak yapilir: model.fit ve model.compile ile\n",
        "* Eger `tf.keras.losses` siniflarini kullaniyorsaniz, kayip indirgemesinin ozellikle `NONE` ya da `SUM` olarak belirtilmesi gerekmektedir. `AUTO` ve `SUM_OVER_BATCH_SIZE` ise `tf.distribute.Strategy` ile birlikte kullanilamaz. Cunku kullanicilarin `AUTO` kullanmadan once yaptiklari indirgemenin o anki dagitim ornegindeki dogrulugundan emin olmalari gerekir. `SUM_OVER_BATCH_SIZE` kullanilamaz cunku su anki haliyle sadece kopyadaki ornek sayisina bolum yapip asil toplam ornek sayisina bolme islemini kullaniciya birakir, ki bu cok kolay gozden kacabilecek bir noktadir. Onun yerine kullanicinin indirgemeyi kendilerinin yapmalarini istiyoruz.\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "iuKuNXPORfqJ"
      },
      "source": [
        "## Egitim dongusu"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab_type": "code",
        "id": "47BLVkRkVQDO",
        "colab": {}
      },
      "source": [
        "with strategy.scope():\n",
        "  def train_step():\n",
        "    def step_fn(inputs):\n",
        "      images, labels = inputs\n",
        "      logits = model(images)\n",
        "      cross_entropy = tf.nn.sparse_softmax_cross_entropy_with_logits(\n",
        "          logits=logits, labels=labels)\n",
        "      loss = tf.reduce_sum(cross_entropy) * (1.0 / BATCH_SIZE)\n",
        "      train_op = optimizer.minimize(loss)\n",
        "      with tf.control_dependencies([train_op]):\n",
        "        return tf.identity(loss)\n",
        "\n",
        "    per_replica_losses = strategy.experimental_run(\n",
        "        step_fn, train_iterator)\n",
        "    mean_loss = strategy.reduce(\n",
        "        tf.distribute.ReduceOp.SUM, per_replica_losses, axis=None)\n",
        "    return mean_loss"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab_type": "code",
        "id": "7x7s5iYAYSGD",
        "colab": {}
      },
      "source": [
        "with strategy.scope():\n",
        "  iterator_init = train_iterator.initialize()\n",
        "  var_init = tf.global_variables_initializer()\n",
        "  loss = train_step()\n",
        "  with tf.Session() as sess:\n",
        "    sess.run([var_init])\n",
        "    for epoch in range(EPOCHS):\n",
        "      sess.run([iterator_init])\n",
        "      for step in range(10000):\n",
        "        if step % 1000 == 0:\n",
        "          print('Epoch {} Step {} Loss {:.4f}'.format(epoch+1,\n",
        "                                                      step,\n",
        "                                                      sess.run(loss)))"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "6hEJNsokjOKs"
      },
      "source": [
        "## Sirada ne var?\n",
        "\n",
        "Simdi `tf.distribute.Strategy` API'yini kendi modellerinizde deneyin. "
      ]
    }
  ]
}